home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / gnu / oleo_src.lha / src / io_utils.c < prev    next >
C/C++ Source or Header  |  1992-08-18  |  26KB  |  1,327 lines

  1. /*    Copyright (C) 1990 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 1, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23.  
  24. #include "sysdef.h"
  25.  
  26. #include "global.h"
  27. #include "cell.h"
  28.  
  29. extern VOIDSTAR ck_malloc EXT1(size_t);
  30. extern VOIDSTAR ck_realloc EXT2(void *,size_t);
  31. extern double astof EXT1(char **);
  32. extern long astol EXT1(char **);
  33.  
  34. extern unsigned short default_width;
  35.  
  36. extern CELLREF curow,cucol;
  37.  
  38. extern struct rng screen;
  39.  
  40. extern int default_fmt;
  41. extern char numb_oflo[];
  42.  
  43. #ifdef TEST
  44.  
  45. extern void panic EXT1N(const char *);
  46. #endif
  47.  
  48. char *bname[] = {
  49.     "#FALSE","#TRUE"
  50. };
  51.  
  52. #ifndef ASM_INF
  53. #ifdef __GNUC__
  54. __asm(".globl ___plinf");
  55. __asm("___plinf: .double 0rinf");
  56. __asm(".globl ___neinf");
  57. __asm("___neinf: .double 0r-inf");
  58. __asm(".globl ___nan");
  59. __asm("___nan: .double 0rnan");
  60. #else
  61. double __plinf = 1e500;
  62. double __neinf = -1e500;
  63. double __nan = 1e500/ -1e500;
  64. #endif
  65. #endif
  66.  
  67. const char nname[] = "#NOT_A_NUMBER";
  68. const char iname[] = "#INFINITY";
  69. const char mname[] = "#MINUS_INFINITY";
  70.  
  71.  
  72. /* Slightly larger than the maximum exponent we ever expect to see */
  73. #define BIGFLT 309
  74. #ifdef TEST
  75. char print_buf[1024*8];
  76. #else
  77. char print_buf[BIGFLT+20];
  78. #endif
  79.  
  80.  
  81. /* Functions, etc for dealing with cell contents being displayed
  82.    on top of other cells. */
  83.  
  84. struct slops {
  85.     int s_alloc,s_used;
  86.     struct s {
  87.         CELLREF row,clo,chi;
  88.     } s_b[1];
  89. };
  90.  
  91. void
  92. flush_slops FUN1(VOIDSTAR,where)
  93. {
  94.     struct slops *s;
  95.  
  96.     s=where;
  97.     if(s)
  98.         s->s_used=0;
  99. }
  100.  
  101. int
  102. find_slop FUN5(VOIDSTAR, where, CELLREF,r, CELLREF,c, CELLREF *,cclp, CELLREF *,cchp)
  103. {
  104.     int n;
  105.     struct slops *s;
  106.  
  107.     s= where;
  108.     if(!s)
  109.         return 0;
  110.     for(n=0;n<s->s_used;n++) {
  111.         if(s->s_b[n].row==r && s->s_b[n].clo<=c && s->s_b[n].chi>=c) {
  112.             *cclp=s->s_b[n].clo;
  113.             *cchp=s->s_b[n].chi;
  114.             return 1;
  115.         }
  116.     }
  117.     return 0;
  118. }
  119.  
  120. void
  121. kill_slop FUN4(VOIDSTAR,where, CELLREF,r, CELLREF,clo, CELLREF,chi)
  122. {
  123.     int n;
  124.     struct slops *s;
  125.  
  126.     s=where;
  127.     for(n=0;n<s->s_used;n++) {
  128.         if(s->s_b[n].row==r && s->s_b[n].clo==clo && s->s_b[n].chi==chi) {
  129.             --(s->s_used);
  130.             s->s_b[n]=s->s_b[s->s_used];
  131.             return;
  132.         }
  133.     }
  134. }
  135.  
  136. void
  137. set_slop FUN4(VOIDSTAR *,wherep, CELLREF,r, CELLREF,clo, CELLREF,chi)
  138. {
  139.     int n;
  140.     struct slops **sp;
  141.  
  142.     sp= (struct slops **)wherep;
  143.     if(!*sp) {
  144.         (*sp)=ck_malloc(sizeof(struct slops)+2*sizeof(struct s));
  145.         (*sp)->s_alloc=2;
  146.         (*sp)->s_used=1;
  147.         n=0;
  148.     } else {
  149.         n= (*sp)->s_used++;
  150.         if((*sp)->s_alloc==n) {
  151.             (*sp)->s_alloc=n*2;
  152.  
  153.             (*sp)=ck_realloc((*sp),sizeof(struct slops)+n*2*sizeof(struct s));
  154.         }
  155.     }
  156.     (*sp)->s_b[n].row=r;
  157.     (*sp)->s_b[n].clo=clo;
  158.     (*sp)->s_b[n].chi=chi;
  159. }
  160.  
  161. void
  162. change_slop FUN6(VOIDSTAR,where, CELLREF,r, CELLREF,olo, CELLREF,ohi, CELLREF,lo, CELLREF,hi)
  163. {
  164.     int n;
  165.     struct slops *s;
  166.  
  167.     s= where;
  168.     for(n=0;n<s->s_used;n++) {
  169.         if(s->s_b[n].row==r && s->s_b[n].clo==olo && s->s_b[n].chi==ohi) {
  170.             s->s_b[n].clo=lo;
  171.             s->s_b[n].chi=hi;
  172.             return;
  173.         }
  174.     }
  175. }
  176.  
  177. /* Stuff for dealing with width of columns */
  178. /* This isn't the best place for it, but here it is. . . */
  179.  
  180. struct width {
  181.     struct width *prev,*next;
  182.     CELLREF w_low,w_high;
  183.     unsigned short wids[1];
  184. };
  185.  
  186. struct width *wid_beg = 0;
  187. struct width *wid_end = 0;
  188.  
  189. #define WID_BUF 1;
  190.  
  191. unsigned short
  192. get_width FUN1(CELLREF, col)
  193. {
  194.     struct width *my_width;
  195.     unsigned short n;
  196.  
  197.     if(!wid_beg) {
  198.         n=default_width;
  199.     } else {
  200.         for(my_width=wid_beg;my_width && col>my_width->w_high;my_width=my_width->next)
  201.             ;
  202.         if(!my_width || col<my_width->w_low)
  203.             n=default_width;
  204.         else {
  205.             if(col<=my_width->w_high) {
  206.                 n=my_width->wids[col-my_width->w_low];
  207.                 if(n==0)
  208.                     n=default_width;
  209.                 else
  210.                     --n;
  211.             } else
  212.                 n=default_width;
  213.         }
  214.     }
  215.     /* if(n>numc)
  216.         n=numc; */
  217.     return n;
  218. }
  219.  
  220. /* This is like get_width, but it returns width+1, or zero if the width is default */
  221. unsigned short
  222. get_nodef_width FUN1(CELLREF, col)
  223. {
  224.     struct width *my_width;
  225.     unsigned short n;
  226.  
  227.     if(!wid_beg)
  228.         return 0;
  229.  
  230.     for(my_width=wid_beg;my_width && col>my_width->w_high;my_width=my_width->next)
  231.         ;
  232.     if(!my_width || col<my_width->w_low)
  233.         return 0;
  234.     if(col<=my_width->w_high) {
  235.         n=my_width->wids[col-my_width->w_low];
  236.         if(n==0)
  237.             return 0;
  238.         return n;
  239.     }
  240.     return 0;
  241. }
  242.  
  243. void
  244. set_width FUN2(CELLREF, col, unsigned short, wid)
  245. {
  246.     struct width *my_wid;
  247.     struct width *tmp_wid;
  248.  
  249.     if(!wid_beg) {
  250.         wid_beg=wid_end=(struct width *)ck_malloc(sizeof(struct width));
  251.         wid_beg->prev=0;
  252.         wid_beg->next=0;
  253.         wid_beg->w_low=col;
  254.         wid_beg->w_high=col;
  255.         wid_beg->wids[0]=wid;
  256.         return;
  257.     }
  258.  
  259.     for(tmp_wid=wid_beg;tmp_wid;tmp_wid=tmp_wid->next)
  260.         if(col<=tmp_wid->w_high)
  261.             break;
  262.  
  263.     if(!tmp_wid) {
  264.         if(wid_end->w_high==col-1) {
  265.             wid_end->w_high++;
  266.  
  267.             wid_end=ck_realloc(wid_end,sizeof(struct width)+(wid_end->w_high-wid_end->w_low)*sizeof(unsigned short));
  268.             wid_end->wids[col-wid_end->w_low]=wid;
  269.             if(wid_end->prev)
  270.                 wid_end->prev->next=wid_end;
  271.             else
  272.                 wid_beg=wid_end;
  273.         } else {
  274.             my_wid=(struct width *)ck_malloc(sizeof(struct width));
  275.             my_wid->w_high=col;
  276.             my_wid->w_low=col;
  277.             my_wid->wids[0]=wid;
  278.             my_wid->next=0;
  279.             my_wid->prev=wid_end;
  280.             wid_end->next=my_wid;
  281.             wid_end=my_wid;
  282.         }
  283.         return;
  284.     }
  285.  
  286.     if(col>=tmp_wid->w_low) {
  287.         tmp_wid->wids[col-tmp_wid->w_low]=wid;
  288.         return;
  289.     }
  290.  
  291.     if(tmp_wid->prev && tmp_wid->prev->w_high==col-1) {
  292.         if(col+1==tmp_wid->w_low) {
  293.             struct width *w1,*w2;
  294.  
  295.             w1=tmp_wid->prev;
  296.             w2=tmp_wid;
  297.             my_wid=(struct width *)ck_malloc(sizeof(struct width)+(w2->w_high-w1->w_low)*sizeof(unsigned short));
  298.             my_wid->prev=w1->prev;
  299.             my_wid->next=w2->next;
  300.             my_wid->w_high=w2->w_high;
  301.             my_wid->w_low=w1->w_low;
  302.  
  303.             bcopy(w1->wids,&(my_wid->wids[0]),(1+w1->w_high-w1->w_low)*sizeof(unsigned short));
  304.             bcopy(w2->wids,&(my_wid->wids[w2->w_low-my_wid->w_low]),(1+w2->w_high-w2->w_low)*sizeof(unsigned short));
  305.             my_wid->wids[col-my_wid->w_low]=wid;
  306.  
  307.             if(my_wid->prev)
  308.                 my_wid->prev->next=my_wid;
  309.             else
  310.                 wid_beg=my_wid;
  311.             if(my_wid->next)
  312.                 my_wid->next->prev=my_wid;
  313.             else
  314.                 wid_end=my_wid;
  315.             free(w1);
  316.             free(w2);
  317.         } else {
  318.             tmp_wid=tmp_wid->prev;
  319.             tmp_wid->w_high++;
  320.  
  321.             tmp_wid=(struct width *)ck_realloc(tmp_wid,sizeof(struct width)+(tmp_wid->w_high-tmp_wid->w_low)*sizeof(unsigned short));
  322.             tmp_wid->wids[tmp_wid->w_high-tmp_wid->w_low]=wid;
  323.             tmp_wid->next->prev=tmp_wid;
  324.             if(tmp_wid->prev)
  325.                 tmp_wid->prev->next=tmp_wid;
  326.             else
  327.                 wid_beg=tmp_wid;
  328.         }
  329.         return;
  330.     }
  331.     if(col+1==tmp_wid->w_low) {
  332.         my_wid=(struct width *)ck_malloc(sizeof(struct width)+(1+tmp_wid->w_high-tmp_wid->w_low)*sizeof(unsigned short));
  333.         my_wid->w_high=tmp_wid->w_high;
  334.         my_wid->w_low=col;
  335.         my_wid->wids[0]=wid;
  336.         bcopy(&(tmp_wid->wids[0]),&(my_wid->wids[1]),(tmp_wid->w_high-tmp_wid->w_low)*sizeof(unsigned short));
  337.         my_wid->prev=tmp_wid->prev;
  338.         my_wid->next=tmp_wid->next;
  339.         if(my_wid->next)
  340.             my_wid->next->prev=my_wid;
  341.         else
  342.             wid_end=my_wid;
  343.         if(my_wid->prev)
  344.             my_wid->prev->next=my_wid;
  345.         else
  346.             wid_beg=my_wid;
  347.         free(tmp_wid);
  348.         return;
  349.     }
  350.     my_wid=(struct width *)ck_malloc(sizeof(struct width));
  351.     my_wid->w_high=col;
  352.     my_wid->w_low=col;
  353.     my_wid->wids[0]=wid;
  354.     my_wid->next=tmp_wid;
  355.     my_wid->prev=tmp_wid->prev;
  356.     tmp_wid->prev=my_wid;
  357.     if(my_wid->prev)
  358.         my_wid->prev->next=my_wid;
  359.     else
  360.         wid_beg=my_wid;
  361.     return;
  362. }
  363.  
  364. unsigned short
  365. next_widths FUN2(CELLREF *,c1, CELLREF *,c2)
  366. {
  367.     static struct width *wid;
  368.     static int n;
  369.     static int nhi;
  370.  
  371.     unsigned short ret;
  372.     int m;
  373.  
  374.     if(c1==0) {
  375.         wid=wid_beg;
  376.         n=0;
  377.         if(wid)
  378.             nhi=wid->w_high-wid->w_low;
  379.         return 0;
  380.     }
  381.     for(;wid;wid=wid->next,n=0,nhi=wid->w_high-wid->w_low) {
  382.         for(;n<=nhi;n++) {
  383.             if(wid->wids[n]==0)
  384.                 continue;
  385.             ret=wid->wids[n];
  386.             for(m=n+1;m<=nhi && wid->wids[m]==ret;m++)
  387.                 ;
  388.             *c1=wid->w_low+n;
  389.             *c2=wid->w_low+m-1;
  390.             n=m;
  391.             if(n>nhi) {
  392.                 n=0;
  393.                 wid=wid->next;
  394.                 if(wid)
  395.                     nhi=wid->w_high-wid->w_low;
  396.             }
  397.             return ret;
  398.         }
  399.     }
  400.     return 0;
  401. }
  402.  
  403. void
  404. flush_widths FUN0()
  405. {
  406.     struct width *w,*wn;
  407.  
  408.     for(w=wid_beg;w;w=wn) {
  409.         wn=w->next;
  410.         free(w);
  411.     }
  412.     wid_beg=0;
  413. }
  414.  
  415. void
  416. shift_widths FUN1(int, over)
  417. {
  418.     struct width *w, *wtmp;
  419.  
  420.     for(w=wid_beg;w;w=w->next) {
  421.         if(over<0 && w->w_low<= -over) {
  422.             if(w->w_high<=MIN_COL-over) {
  423.                 if(w->prev)
  424.                     w->prev->next=w->next;
  425.                 else
  426.                     wid_beg=w->next;
  427.                 if(w->next)
  428.                     w->next=w->prev;
  429.                 else
  430.                     wid_end=w->prev;
  431.             } else {
  432.                 wtmp=ck_malloc(sizeof(struct width)+(w->w_high+over-MIN_COL)*sizeof(unsigned short));
  433.  
  434.                 if(w->next) {
  435.                     wtmp->next=w->next;
  436.                     w->next->prev=wtmp;
  437.                 } else
  438.                     wid_end=wtmp;
  439.                 if(w->prev) {
  440.                     wtmp->prev=w->prev;
  441.                     w->prev->next=wtmp;
  442.                 } else
  443.                     wid_beg=wtmp;
  444.                 wtmp->w_low=MIN_COL;
  445.                 wtmp->w_high=w->w_high+over;
  446.                 bcopy(&(w->wids[MIN_COL-over-w->w_low]),&(wtmp->wids[0]),(wtmp->w_high+1-wtmp->w_low)*sizeof(unsigned short));
  447.             }
  448.             free(w);
  449.         } else if(over>0 && w->w_high>=MAX_COL-over) {
  450.             if(w->w_low>=MAX_COL-over) {
  451.                 if(w->prev)
  452.                     w->prev->next=w->next;
  453.                 else
  454.                     wid_beg=w->next;
  455.                 if(w->next)
  456.                     w->next=w->prev;
  457.                 else
  458.                     wid_end=w->prev;
  459.                 free(w);
  460.             } else {
  461.                 w->w_high=MAX_COL;
  462.                 w->w_low+=over;
  463.  
  464.                 w=ck_realloc(w,sizeof(struct width)+(w->w_high-w->w_low)*sizeof(unsigned short));
  465.                 if(w->next)
  466.                     w->next->prev=w;
  467.                 else
  468.                     wid_end=w;
  469.                 if(w->prev)
  470.                     w->prev->next=w;
  471.                 else
  472.                     wid_beg=w;
  473.             }
  474.         } else {
  475.             w->w_low+=over;
  476.             w->w_high+=over;
  477.         }
  478.     }
  479. }
  480.  
  481. /* Structures/vars/functions for dealing with formatting floating-point
  482.    numbers, etc */
  483.  
  484. struct user_fmt {
  485.     char *p_hdr,*n_hdr;
  486.     char *p_trl,*n_trl;
  487.     char *zero,*comma,*decpt;
  488.     unsigned char prec;
  489.     double scale;
  490. };
  491.  
  492.     /* Routines for formatting cell values */
  493. static char *pr_flt EXT3(double, struct user_fmt *, int);
  494. static char *pr_int EXT3(long, struct user_fmt *, int);
  495.  
  496. struct user_fmt dol = {
  497.     "$","($",     0,")",  "$0",",", ".", PRC_FLT,   1    };
  498.  
  499. struct user_fmt cma = {
  500.       0, "(",     0,")",  "0", ",", ".", PRC_FLT,   1    };
  501.  
  502. struct user_fmt pct = {
  503.       0, "-",   "%","%",  "0%",  0, ".", PRC_FLT, 100    };
  504.  
  505. struct user_fmt fxt = {
  506.       0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    };
  507.  
  508. /* Variables */
  509.  
  510. struct user_fmt u[16] = {
  511.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  512.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  513.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  514.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  515.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  516.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  517.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  518.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  519.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  520.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  521.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  522.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  523.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  524.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  525.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  526.   {      0, "-",     0,  0,  "0",   0, ".", PRC_FLT,   1    },
  527. };
  528.  
  529.  
  530. /* Turn a floating-point number into the canonical text form.  This scribbles
  531.    on print_buf */
  532. char *
  533. flt_to_str FUN1(double, val)
  534. {
  535.     double f;
  536.     extern double fabs();
  537.  
  538.     if(val==__plinf)
  539.         return iname;
  540.     if(val==__neinf)
  541.         return mname;
  542.     f=fabs(val);
  543.     if(f>=1e6 || (f>0 && f<=9.9999e-6)) {
  544.         sprintf(print_buf,"%e",val);
  545.         return print_buf;
  546.     }
  547.     return pr_flt(val,&fxt,PRC_FLT);
  548. }
  549.  
  550. /* create the human-readable version of the contents of a cell
  551.    This scribbles on print-buf bigtime */
  552.  
  553. char *
  554. print_cell FUN1(CELL *,cp)
  555. {
  556.     int j;
  557.     int p;
  558.     long num;
  559.     static char zeroes[] = "000000000000000";
  560.  
  561.     j=GET_FMT(cp);
  562.  
  563.     if(j==FMT_DEF)
  564.         j=default_fmt;
  565.     if(j==FMT_HID || GET_TYP(cp)==0)
  566.         return "";
  567.  
  568.     if(GET_TYP(cp)==TYP_STR)
  569.         return cp->cell_str;
  570.     if(GET_TYP(cp)==TYP_BOL) {
  571. #ifdef TEST
  572.         if(cp->cell_bol<0 || cp->cell_bol>1)
  573.             panic("Bool %d out of range",cp->cell_bol);
  574. #endif
  575.         return bname[cp->cell_bol];
  576.     }
  577.     if(GET_TYP(cp)==TYP_ERR) {
  578. #ifdef TEST
  579.         if(cp->cell_err>ERR_MAX || cp->cell_err<0)
  580.             panic("Error %d out of range",cp->cell_err);
  581. #endif
  582.         return ename[cp->cell_err];
  583.     }
  584.     if(GET_TYP(cp)==TYP_FLT) {
  585.         p=GET_PRC(j);
  586.         switch(j|PRC_FLT) {
  587.         case FMT_GPH:
  588.             if(cp->cell_flt<0) {
  589.                 j='-';
  590.                 num = -(cp->cell_flt);
  591.             } else if(cp->cell_flt>=1) {
  592.                 j='+';
  593.                 num= (cp->cell_flt);
  594.             } else {
  595.                 j='0';
  596.                 num=1;
  597.             }
  598.         graph:
  599.             if(num>=sizeof(print_buf)) {
  600.                 error_msg("Cannot graph %d '%c'",p,j);
  601.                 num=sizeof(print_buf)-1;
  602.             }
  603.             print_buf[num]='\0';
  604.             while(--num>=0)
  605.                 print_buf[num]=j;
  606.             return print_buf;
  607.  
  608.         case FMT_USR:
  609.             return pr_flt(cp->cell_flt,&u[p],u[p].prec);
  610.  
  611.         case FMT_GEN:
  612.         {
  613.             double f;
  614.             extern double fabs();
  615.  
  616.             f=fabs(cp->cell_flt);
  617.             if(f>=1e6 || (f>0 && f<=9.9999e-6))
  618.                 goto handle_exp;
  619.             return pr_flt(cp->cell_flt,&fxt,p);
  620.         }
  621.  
  622.         case FMT_DOL:
  623.             return pr_flt(cp->cell_flt,&dol,p);
  624.  
  625.         case FMT_CMA:
  626.             return pr_flt(cp->cell_flt,&cma,p);
  627.  
  628.         case FMT_PCT:
  629.             return pr_flt(cp->cell_flt,&pct,p);
  630.  
  631.         case FMT_FXT:
  632.             return pr_flt(cp->cell_flt,&fxt,p);
  633.  
  634.         case FMT_EXP:
  635.         handle_exp:
  636.             if(cp->cell_flt==__plinf)
  637.                 return iname;
  638.             if(cp->cell_flt==__neinf)
  639.                 return mname;
  640.             if(p==PRC_FLT)
  641.                 sprintf(print_buf,"%e",cp->cell_flt);
  642.             else
  643.                 sprintf(print_buf,"%.*e",p,cp->cell_flt);
  644.             return print_buf;
  645. #ifdef TEST
  646.         default:
  647.             panic("Unknown format %d",j);
  648.             return 0;
  649. #endif
  650.         }
  651.     }
  652.  
  653.     if(GET_TYP(cp)==TYP_INT) {
  654.         p=GET_PRC(j);
  655.         switch(j|PRC_FLT) {
  656.         case FMT_GPH:
  657.             if(cp->cell_int<0) {
  658.                 j='-';
  659.                 num = -(cp->cell_int);
  660.             } else if(cp->cell_int>=1) {
  661.                 j='+';
  662.                 num = (cp->cell_int);
  663.             } else {
  664.                 j='0';
  665.                 num = 1;
  666.             }
  667.             goto graph;
  668.  
  669.         case FMT_USR:
  670.             return pr_int(cp->cell_int,&u[p],u[p].prec);
  671.  
  672.         case FMT_GEN:
  673.             sprintf(print_buf,"%ld",cp->cell_int);
  674.             return print_buf;
  675.  
  676.         case FMT_DOL:
  677.             return pr_int(cp->cell_int,&dol,p);
  678.  
  679.         case FMT_CMA:
  680.             return pr_int(cp->cell_int,&cma,p);
  681.  
  682.         case FMT_PCT:
  683.             return pr_int(cp->cell_int,&pct,p);
  684.  
  685.         case FMT_FXT:
  686.             if(p!=PRC_FLT && p!=0)
  687.                 sprintf(print_buf,"%ld.%.*s",cp->cell_int,p,zeroes);
  688.             else
  689.                 sprintf(print_buf,"%ld",cp->cell_int);
  690.             return print_buf;
  691.  
  692.         case FMT_EXP:
  693.             if(p!=PRC_FLT)
  694.                 sprintf(print_buf,"%.*e",p,(double)(cp->cell_int));
  695.             else
  696.                 sprintf(print_buf,"%e",(double)(cp->cell_int));
  697.             return print_buf;
  698. #ifdef TEST
  699.         default:
  700.             panic("Unknown format %d",j);
  701.             return 0;
  702. #endif
  703.         }
  704.     }
  705. #ifdef TEST
  706.     panic("Unknown cell type %d",GET_TYP(cp));
  707. #endif
  708.     return 0;
  709. }
  710.  
  711. /* Return the value of ROW,COL in a human-readable fashion
  712.    In paticular, strings have "" around them, and are \\ed
  713.  */
  714. char *
  715. cell_value_string FUN2(CELLREF, row, CELLREF, col)
  716. {
  717.     CELL *cp;
  718.     extern char *bname[];
  719.     extern char print_buf[];
  720.     extern char *flt_to_str();
  721.     extern char *backslash_a_string();
  722.  
  723.     cp=find_cell(row,col);
  724.     if(!cp || !GET_TYP(cp))
  725.         return "";
  726.     switch(GET_TYP(cp)) {
  727.     case TYP_FLT:
  728.         return flt_to_str(cp->cell_flt);
  729.  
  730.     case TYP_INT:
  731.         sprintf(print_buf,"%ld",cp->cell_int);
  732.         return print_buf;
  733.  
  734.     case TYP_STR:
  735.         return backslash_a_string(cp->cell_str,1);
  736.  
  737.     case TYP_BOL:
  738.         return bname[cp->cell_bol];
  739.  
  740.     case TYP_ERR:
  741.         return ename[cp->cell_err];
  742. #ifdef TEST
  743.     default:
  744.         panic("unknown type %d in cell_value_string",GET_TYP(cp));
  745. #endif
  746.     }
  747.     return 0;
  748. }
  749.  
  750. static char *
  751. pr_int FUN3(long,val, struct user_fmt *,fmt, int,prec)
  752. {
  753.     char *pf, *pff, *pt;
  754.     long int n;
  755.     int nn=0;
  756.  
  757.     pt= &print_buf[sizeof(print_buf)-1];
  758.     *pt='\0';
  759.  
  760.     n= fmt->scale * ((val<0) ? -val : val);
  761.     if(n==0)
  762.         return fmt->zero ? fmt->zero : "";
  763.  
  764.     pf=pff= (val<0) ? fmt->n_trl : fmt->p_trl;
  765.     if(pf && *pf) {
  766.         while(*pf)
  767.             pf++;
  768.         do
  769.             *--pt= *--pf;
  770.         while(pf!=pff);
  771.     }
  772.  
  773.     if(prec!=PRC_FLT && prec!=0) {
  774.         while(prec-->0)
  775.             *--pt='0';
  776.         pf=pff=fmt->decpt;
  777.         if(pf) {
  778.             while(*pf)
  779.                 pf++;
  780.             do *--pt= *--pf;
  781.             while(pf!=pff);
  782.         }
  783.         /* *--pt='.'; */
  784.     }
  785.     do {
  786.         *--pt= (n%10)+'0';
  787.         n/=10;
  788.         if(nn++==2 && n>0) {
  789.             if(fmt->comma && *(fmt->comma)) {
  790.                 for(pf=pff=fmt->comma;*pf;pf++)
  791.                     ;
  792.                 do *--pt= *--pf;
  793.                 while(pf!=pff);
  794.             }
  795.             nn=0;
  796.         }
  797.     } while(n>0);
  798.  
  799.     pf=pff= (val<0) ? fmt->n_hdr : fmt->p_hdr;
  800.     if(pf && *pf) {
  801.         while(*pf)
  802.             pf++;
  803.         do *--pt= *--pf;
  804.         while(pf!=pff);
  805.     }
  806.     return pt;
  807. }
  808.  
  809. static char *
  810. pr_flt FUN3(double,val, struct user_fmt *,fmt, int,prec)
  811. {
  812.     char *iptr;
  813.     char *fptr;
  814.     char *pptr;
  815.     char *pf,*pff;
  816.     double fract, integer, tmpval;
  817.     int n;
  818.     int isneg;
  819.     int comlen;
  820.  
  821.     val*=fmt->scale;
  822.  
  823.     if(val==__plinf)
  824.         return iname;
  825.     if(val==__neinf)
  826.         return mname;
  827.     if(val!=val)
  828.         return nname;
  829.  
  830.     iptr= &print_buf[BIGFLT];
  831.     fptr= &print_buf[BIGFLT];
  832.  
  833.  
  834.     if(val<0) {
  835.         isneg=1;
  836.         val = -val;
  837.     } else
  838.         isneg=0;
  839.  
  840.     if(val==0)
  841.         return fmt->zero ? fmt->zero : "";
  842.  
  843.     comlen=0;
  844.     if(fmt->comma && *(fmt->comma))
  845.         for(pf=fmt->comma;*pf;comlen++,pf++)
  846.             ;
  847.  
  848.     fract=modf(val,&integer);
  849.     n=0;
  850.     do {
  851.         if(iptr< &print_buf[comlen])
  852.             return numb_oflo;
  853.         tmpval=modf(integer/10,&integer);
  854.         *--iptr='0'+(int)((tmpval+.01)*10);
  855.         if(n++==2 && integer) {
  856.             n=0;
  857.             if(comlen) {
  858.                 pff=fmt->comma;
  859.                 pf=pff+comlen;
  860.                 do *--iptr= *--pf;
  861.                 while(pf!=pff);
  862.             }
  863.         }
  864.     } while(integer);
  865.  
  866.     if(prec) {
  867.         int p1;
  868.  
  869.         p1= (prec==PRC_FLT) ? 15 : (prec>0) ? prec : -prec;
  870.         pf=fmt->decpt;
  871.         while(pf && *pf)
  872.             *fptr++= *pf++;
  873.         /* *fptr++='.'; */
  874.         if(fract) {
  875.             do {
  876.                 fract = modf(fract * 10,&tmpval);
  877.                 *fptr++ = '0' + (int)tmpval;
  878.             } while (--p1 && fract);
  879.         }
  880.         if(prec>0 && prec!=PRC_FLT)
  881.             while(p1--)
  882.                 *fptr++='0';
  883.         else {
  884.             while(fptr[-1]=='0')
  885.                 --fptr;
  886.             while(!isdigit(fptr[-1]))
  887.                 --fptr;
  888.             *fptr='\0';
  889.         }
  890.     }
  891.     if(fract) {
  892.         (void)modf(fract * 10, &tmpval);
  893.         if(tmpval>4) {
  894.             iptr[-1]='0';
  895.             for(pptr=fptr-1;;--pptr) {
  896.                 if(!isdigit(*pptr))
  897.                     continue;
  898.                 else if(*pptr=='9') {
  899.                     if(pptr==fptr-1 && pptr>&print_buf[BIGFLT] && (prec<0 || prec==PRC_FLT)) {
  900.                         --fptr;
  901.                         while(!isdigit(pptr[-1])) {
  902.                             --fptr;
  903.                             --pptr;
  904.                         }
  905.                         *pptr='\0';
  906.                     } else
  907.                         *pptr='0';
  908.                 } else {
  909.                     (*pptr)++;
  910.                     break;
  911.                 }
  912.             }
  913.             if(pptr<iptr) {
  914.                 --iptr;
  915.                 if(n==3) {
  916.                     n= *iptr++;
  917.                     for(pf=pff=fmt->comma;*pf;pf++)
  918.                         ;
  919.                     do *--iptr= *--pf;
  920.                     while(pf!=pff);
  921.                     *--iptr=n;
  922.                 }
  923.             }
  924.         }
  925.     }
  926.     pf=pff= (isneg) ? fmt->n_hdr : fmt->p_hdr;
  927.     if(pf && *pf) {
  928.         while(*pf)
  929.             pf++;
  930.         do *--iptr= *--pf;
  931.         while(pf!=pff);
  932.     }
  933.  
  934.     pf=(isneg) ? fmt->n_trl : fmt->p_trl;
  935.     while(pf && *pf)
  936.         *fptr++ = *pf++;
  937.     *fptr=0;
  938.     return iptr;
  939. }
  940.  
  941. char *
  942. adjust_prc FUN5(char *,oldp, CELL *,cp, int,width, int,smallwid, int,just)
  943. {
  944.     int fmt;
  945.     int prc;
  946.     struct user_fmt *ufmt;
  947.     char *bptr;
  948.     char *eptr;
  949.     int len;
  950.  
  951.     fmt=GET_FMT(cp);
  952.     if(fmt==FMT_DEF)
  953.         fmt=default_fmt;
  954.     prc=GET_PRC(fmt);
  955.     switch(fmt|PRC_FLT) {
  956.     case FMT_GPH:
  957.     case FMT_HID:
  958.         return numb_oflo;
  959.     case FMT_DOL:
  960.         ufmt= &dol;
  961.         goto deal_fmt;
  962.  
  963.     case FMT_CMA:
  964.         ufmt= &cma;
  965.         goto deal_fmt;
  966.  
  967.     case FMT_PCT:
  968.         ufmt= &cma;
  969.         goto deal_fmt;
  970.  
  971.     case FMT_FXT:
  972.         ufmt= &fxt;
  973.         goto deal_fmt;
  974.  
  975.     case FMT_USR:
  976.         ufmt= &u[prc];
  977.         prc=ufmt->prec;
  978.         goto deal_fmt;
  979.  
  980.     case FMT_GEN:
  981.         if(prc!=PRC_FLT)
  982.             return numb_oflo;
  983.         if(index(oldp,'e') || !index(oldp,'.'))
  984.             goto handle_exp;
  985.  
  986.         ufmt= &fxt;
  987.         prc=PRC_FLT;
  988.         goto deal_fmt;
  989.  
  990.     deal_fmt:
  991.         if(prc!=PRC_FLT)
  992.             return numb_oflo;
  993.         len=strlen(oldp);
  994.         bptr=strstr(oldp,ufmt->decpt);
  995.         if(!bptr)
  996.             return numb_oflo;
  997.         while(eptr=strstr(bptr+1,ufmt->decpt))
  998.             bptr=eptr;
  999.  
  1000.         if(width<bptr-oldp)
  1001.             return numb_oflo;
  1002.         if(bptr-oldp+strlen(ufmt->decpt)>=width)
  1003.             prc=0;
  1004.         else {
  1005.             prc=width-(strlen(ufmt->decpt)+bptr-oldp);
  1006.         }
  1007.         bptr=pr_flt(cp->cell_flt,ufmt,-prc);
  1008.         len=strlen(bptr);
  1009.         if(len>width && prc>0) {
  1010.             bptr=pr_flt(cp->cell_flt,ufmt,-(prc-1));
  1011.             len=strlen(bptr);
  1012.         }
  1013.         if(len>width)
  1014.             return numb_oflo;
  1015.         break;
  1016.  
  1017.     case FMT_EXP:
  1018.     handle_exp:
  1019.         {
  1020.             double f;
  1021.             extern double fabs EXT1(double);
  1022.  
  1023.             f=fabs(cp->cell_flt);
  1024.             if(f>9.99999e99 || f<1e-99)
  1025.                 len=width-7;
  1026.             else /* if(f>9.9999999e9 || f<1e-9) */
  1027.                 len=width-6;
  1028.             /* else
  1029.                 len=width-5; */
  1030.             if(cp->cell_flt<0)
  1031.                 --len;
  1032.             if(len>0) {
  1033.                 sprintf(oldp,"%.*e",len,cp->cell_flt);
  1034.                 len=strlen(oldp);
  1035.                 if(len<=width) {
  1036.                     bptr=oldp;
  1037.                     break;
  1038.                 }
  1039.             }
  1040.         }
  1041.         return numb_oflo;
  1042. #ifdef TEST
  1043.     default:
  1044.         panic("Unknown format %d in adjust_prc()",fmt);
  1045.         bptr=0;
  1046.         len=0;
  1047.         break;
  1048. #endif
  1049.     }
  1050.  
  1051.     /* If we get here, bptr points to a a string of len characters
  1052.        (len<=width) that we want to output */
  1053.     if(len<smallwid) {
  1054.         if(just==JST_RGT || just==JST_CNT) {
  1055.             int n;
  1056.  
  1057.             n= (just==JST_RGT) ? smallwid-len : (1+smallwid-len)/2;
  1058.             for(;;) {
  1059.                 bptr[len+n]=bptr[len];
  1060.                 if(len--==0)
  1061.                     break;
  1062.             }
  1063.             while(n-->=0)
  1064.                 bptr[n]=' ';
  1065.         }
  1066.     }
  1067.     return bptr;
  1068. }
  1069.  
  1070.  
  1071. void
  1072. set_usr_stats FUN2(int,usr_n, char **,usr_buf)
  1073. {
  1074.     int len;
  1075.     int i;
  1076.     char *p_in,*p_out;
  1077.  
  1078.     len=0;
  1079.     for(i=0;i<7;i++)
  1080.         len+=strlen(usr_buf[i]);
  1081.     u[usr_n].p_hdr=ck_malloc(len+7);
  1082.     p_out=u[usr_n].p_hdr;
  1083.     if(usr_buf[0][0]) {
  1084.         p_in=usr_buf[0];
  1085.         while(*p_out++= *p_in++)
  1086.             ;
  1087.     } else
  1088.         *p_out++='\0';
  1089.  
  1090.     if(usr_buf[1][0]) {
  1091.         p_in=usr_buf[1];
  1092.         u[usr_n].n_hdr=p_out;
  1093.         while(*p_out++= *p_in++)
  1094.             ;
  1095.     } else
  1096.         u[usr_n].n_hdr=0;
  1097.  
  1098.     if(usr_buf[2][0]) {
  1099.         p_in=usr_buf[2];
  1100.         u[usr_n].p_trl=p_out;
  1101.         while(*p_out++= *p_in++)
  1102.             ;
  1103.     } else
  1104.         u[usr_n].p_trl=0;
  1105.  
  1106.     if(usr_buf[3][0]) {
  1107.         p_in=usr_buf[3];
  1108.         u[usr_n].n_trl=p_out;
  1109.         while(*p_out++= *p_in++)
  1110.             ;
  1111.     } else
  1112.         u[usr_n].n_trl=0;
  1113.  
  1114.     if(usr_buf[4][0]) {
  1115.         p_in=usr_buf[4];
  1116.         u[usr_n].zero=p_out;
  1117.         while(*p_out++= *p_in++)
  1118.             ;
  1119.     } else
  1120.         u[usr_n].zero=0;
  1121.  
  1122.     if(usr_buf[5][0]) {
  1123.         p_in=usr_buf[5];
  1124.         u[usr_n].comma=p_out;
  1125.         while(*p_out++= *p_in++)
  1126.             ;
  1127.     } else
  1128.         u[usr_n].comma=0;
  1129.  
  1130.     if(usr_buf[6][0]) {
  1131.         p_in=usr_buf[6];
  1132.         u[usr_n].decpt=p_out;
  1133.         while(*p_out++= *p_in++)
  1134.             ;
  1135.     } else
  1136.         u[usr_n].decpt=0;
  1137.  
  1138.     if(!stricmp(usr_buf[7],"float") || !stricmp(usr_buf[7],"f"))
  1139.         u[usr_n].prec=15;
  1140.     else 
  1141.         u[usr_n].prec=astol(&usr_buf[7]);
  1142.  
  1143.     u[usr_n].scale=astof(&usr_buf[8]);
  1144. }
  1145.  
  1146. int
  1147. usr_set_fmts FUN0()
  1148. {
  1149.     int n;
  1150.     int ret = 0;
  1151.  
  1152.     for(n=0;n<16;n++)
  1153.         if(u[n].p_hdr)
  1154.             ret|=1<<n;
  1155.     return ret;
  1156. }
  1157.  
  1158. void
  1159. get_usr_stats FUN2(int,usr_num, char **,usr_buf)
  1160. {
  1161.     static char buf1[30];
  1162.     static char buf2[30];
  1163.     static char NullStr[]="";
  1164.  
  1165.     usr_buf[0]= u[usr_num].p_hdr ? u[usr_num].p_hdr : NullStr;
  1166.     usr_buf[1]= u[usr_num].n_hdr ? u[usr_num].n_hdr : NullStr;
  1167.     usr_buf[2]= u[usr_num].p_trl ? u[usr_num].p_trl : NullStr;
  1168.     usr_buf[3]= u[usr_num].n_trl ? u[usr_num].n_trl : NullStr;
  1169.     usr_buf[4]= u[usr_num].zero ? u[usr_num].zero : NullStr;
  1170.     usr_buf[5]= u[usr_num].comma ? u[usr_num].comma : NullStr;
  1171.     usr_buf[6]= u[usr_num].decpt ? u[usr_num].decpt : NullStr;
  1172.     if(u[usr_num].prec==15)
  1173.         usr_buf[7]="float";
  1174.     else {
  1175.         sprintf(buf1,"%u",u[usr_num].prec);
  1176.         usr_buf[7]=buf1;
  1177.     }
  1178.     sprintf(buf2,"%.12g",u[usr_num].scale);
  1179.     usr_buf[8]=buf2;
  1180. }
  1181.  
  1182. /* Functions for printing out the names of cells and ranges */
  1183.  
  1184. char *
  1185. cell_name FUN2(CELLREF,rr, CELLREF,cc)
  1186. {
  1187.     static char strs[2][20];
  1188.     static num = 0;
  1189.     char *ptr;
  1190.  
  1191.     num = num ? 0 : 1;
  1192.  
  1193. #ifdef A0_REFS
  1194.     ptr= &strs[num][9];
  1195.     sprintf(ptr,"%u",rr);
  1196.     if(cc<MIN_COL+26)
  1197.         *--ptr='A'-MIN_COL+cc;
  1198.     else if(cc<MIN_COL+702) {
  1199.         cc-=MIN_COL+26;
  1200.         *--ptr='A'+cc%26;
  1201.         *--ptr='A'+cc/26;
  1202.     }
  1203. #if MAX_COL>702
  1204.     else if(cc<MIN_COL+18278) {
  1205.         cc-=MIN_COL+702;
  1206.         *--ptr='A'+cc%26;
  1207.         cc/=26;
  1208.         *--ptr='A'+cc%26;
  1209.         *--ptr='A'+cc/26;
  1210.     } else {
  1211.         cc-=MIN_COL+18278;
  1212.         *--ptr='A'+cc%26;
  1213.         cc/=26;
  1214.         *--ptr='A'+cc%26;
  1215.         cc/=26;
  1216.         *--ptr='A'+cc%26;
  1217.         *--ptr='A'+cc/26;
  1218.     }
  1219. #else
  1220.     else
  1221.         panic("Col %u out of range in cell_name()",cc);
  1222. #endif
  1223. #else
  1224.     ptr= &strs[num][0];
  1225.     sprintf(ptr,"r%uc%u",rr,cc);
  1226. #endif
  1227.     return ptr;
  1228. }
  1229.  
  1230. char *
  1231. range_name FUN1(struct rng *,rng)
  1232. {
  1233.     CELLREF lr,lc,hr,hc;
  1234.     static char buf[2][40];
  1235.     static num;
  1236.     char *ptr;
  1237.  
  1238.     ptr= &buf[num][0];
  1239.     num = num ? 0 : 1;
  1240.  
  1241.     lr=rng->lr;
  1242.     lc=rng->lc;
  1243.     hr=rng->hr;
  1244.     hc=rng->hc;
  1245.  
  1246. #ifdef A0_REFS
  1247.     sprintf(ptr,"%s:%s",cell_name(lr,lc),cell_name(hr,hc));
  1248.     return ptr;
  1249. #else
  1250.     if(lr==hr && lc==hc)
  1251.         sprintf(ptr,"r%uc%u",lr,lc);
  1252.     else if(lr==hr && lc!=hc)
  1253.         sprintf(ptr,"r%uc%u:%u",lr,lc,hc);
  1254.     else if(lr!=hr && lc==hc)
  1255.         sprintf(ptr,"r%u:%uc%u",lr,hr,lc);
  1256.     else
  1257.         sprintf(ptr,"r%u:%uc%u:%u",lr,hr,lc,hc);
  1258.     return ptr;
  1259. #endif
  1260. }
  1261.  
  1262.  
  1263. #ifdef A0_REFS
  1264. char *
  1265. col_to_str FUN1(CELLREF, col)
  1266. {
  1267.     static char strs[2][10];
  1268.     static num;
  1269.     char *ptr;
  1270.  
  1271.     ptr= &strs[num][9];
  1272.     num = num ? 0 : 1;
  1273.  
  1274.     if(col<MIN_COL+26)
  1275.         *--ptr='A'-MIN_COL+col;
  1276.     else if(col<MIN_COL+702) {
  1277.         col-=MIN_COL+26;
  1278.         *--ptr='A'+col%26;
  1279.         *--ptr='A'+col/26;
  1280.     } else if(col<MIN_COL+18278) {
  1281.         col-=MIN_COL+702;
  1282.         *--ptr='A'+col%26;
  1283.         col/=26;
  1284.         *--ptr='A'+col%26;
  1285.         *--ptr='A'+col/26;
  1286.     } else {
  1287.         col-=MIN_COL+18278;
  1288.         *--ptr='A'+col%26;
  1289.         col/=26;
  1290.         *--ptr='A'+col%26;
  1291.         col/=26;
  1292.         *--ptr='A'+col%26;
  1293.         *--ptr='A'+col/26;
  1294.     }
  1295.     return ptr;
  1296. }
  1297. #endif
  1298.  
  1299.  
  1300. void
  1301. clear_spreadsheet FUN0()
  1302. {
  1303.     int n;
  1304.     extern int default_jst;
  1305.     extern int default_lock;
  1306.     extern void flush_widths EXT0();
  1307.     extern void flush_everything EXT0();
  1308.     extern void flush_all_timers EXT0();
  1309.  
  1310.     flush_everything();
  1311.     flush_widths();
  1312.     flush_all_timers();
  1313.     for(n=0;n<16;n++) {
  1314.         if(u[n].p_hdr) {
  1315.             free(u[n].p_hdr);
  1316.             u[n].p_hdr=0;
  1317.             u[n].prec=PRC_FLT;
  1318.             u[n].scale=1;
  1319.         }
  1320.     }
  1321.     default_width=8;
  1322.     default_jst=JST_LFT;
  1323.     default_fmt=FMT_GEN;
  1324.     default_lock=LCK_UNL;
  1325. }
  1326.  
  1327.